home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
telecomm
/
zmdm_src.arc
/
ZM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-06-26
|
13KB
|
700 lines
/*
* ACKNOWLEDGEMENTS
*
* ZMDM was derived from rz/sz for Unix posted by
* Chuck Forsberg (...!tektronix!reed!omen!caf ). We
* thank him for his excellent code, and for giving
* us permission to use and distribute his code and
* documentation.
*
* Atari St version by:
* Jwahar Bammi
* usenet: mandrill!bammi@{decvax,sun}.UUCP
* csnet: bammi@mandrill.ces.CWRU.edu
* arpa: bammi@mandrill.ces.CWRU.edu
* CompuServe: 71515,155
*/
/*
* Z M . C
* ZMODEM protocol primitives
* 01-15-87 Chuck Forsberg Omen Technology Inc
*
* Entry point Functions:
* zsbhdr(type, hdr) send binary header
* zshhdr(type, hdr) send hex header
* zgethdr(hdr, eflag) receive header - binary or hex
* zsdata(buf, len, frameend) send data
* zrdata(buf, len) receive data
* stohdr(pos) store position data in Txhdr
* long rclhdr(hdr) recover position offset from header
*/
#include "config.h"
#include "zmdm.h"
#include "common.h"
#ifndef CANFDX
#include "zmodem.h"
#endif
#define xsendline(X) sendline(X)
static char *frametypes[] = {
"Carrier Lost", /* -3 */
"TIMEOUT", /* -2 */
"ERROR", /* -1 */
#define FTOFFSET 3
"ZRQINIT",
"ZRINIT",
"ZSINIT",
"ZACK",
"ZFILE",
"ZSKIP",
"ZNAK",
"ZABORT",
"ZFIN",
"ZRPOS",
"ZDATA",
"ZEOF",
"ZFERR",
"ZCRC",
"ZCHALLENGE",
"ZCOMPL",
"ZCAN",
"ZFREECNT",
"ZCOMMAND",
"ZSTDERR",
"xxxxx"
#define FRTYPES 22 /* Total number of frame types in this array */
/* not including psuedo negative entries */
};
/* Send ZMODEM binary header hdr of type type */
zsbhdr(type, hdr)
register int type;
register char *hdr;
{
register int n;
register unsigned int crc;
vfile2("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
if (type == ZDATA)
for (n = Znulls; --n >=0; )
zsendline(0);
xsendline(ZPAD); xsendline(ZDLE);
if (Txfcs32)
zsbh32(hdr, type);
else {
xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
for (n=4; --n >= 0;) {
zsendline(*hdr);
crc = updcrc((0377& *hdr++), crc);
}
crc = updcrc(0,updcrc(0,crc));
zsendline(crc>>8);
zsendline(crc);
}
if (type != ZDATA)
flush_modem();
}
/* Send ZMODEM binary header hdr of type type */
zsbh32(hdr, type)
register char *hdr;
register int type;
{
register int n;
register unsigned long crc;
xsendline(ZBIN32); zsendline(type);
crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
for (n=4; --n >= 0;) {
zsendline(*hdr);
crc = UPDC32((0377& *hdr++), crc);
}
crc = ~crc;
for (n=4; --n >= 0;) {
zsendline((unsigned int)(crc&0xFFFF)); crc >>= 8;
}
}
/* Send ZMODEM HEX header hdr of type type */
zshhdr(type, hdr)
register int type;
register char *hdr;
{
register int n;
register unsigned int crc;
vfile2("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
zputhex(type);
crc = updcrc(type, 0);
for (n=4; --n >= 0;) {
zputhex(*hdr); crc = updcrc((0377& *hdr++), crc);
}
crc = updcrc(0,updcrc(0,crc));
zputhex(crc>>8); zputhex(crc);
/* Make it printable on remote machine */
sendline(015); sendline(012);
/*
* Uncork the remote in case a fake XOFF has stopped data flow
*/
if (type != ZFIN)
sendline(021);
flush_modem();
}
/*
* Send binary array buf of length length, with ending ZDLE sequence frameend
*/
zsdata(buf, length, frameend)
register char *buf;
register int length, frameend;
{
register unsigned int crc;
vfile("zsdata: length=%d end=%x", length, frameend);
if (Txfcs32)
zsda32(buf, length, frameend);
else {
crc = 0;
for (;--length >= 0;) {
zsendline(*buf);
crc = updcrc((0377& *buf++), crc);
}
xsendline(ZDLE); xsendline(frameend);
crc = updcrc(frameend, crc);
crc = updcrc(0,updcrc(0,crc));
zsendline(crc>>8); zsendline(crc);
}
if (frameend == ZCRCW) {
xsendline(XON); flush_modem();
}
}
zsda32(buf, length, frameend)
register char *buf;
register int length, frameend;
{
register unsigned long crc;
crc = 0xFFFFFFFFL;
for (;--length >= 0;) {
zsendline(*buf); crc = UPDC32((0377& *buf++), crc);
}
xsendline(ZDLE); xsendline(frameend);
crc = UPDC32(frameend, crc);
crc = ~crc;
for (length=4; --length >= 0;) {
zsendline((unsigned int)(crc&0xFFFF)); crc >>= 8;
}
}
/*
* Receive array buf of max length with ending ZDLE sequence
* and CRC. Returns the ending character or error code.
*/
zrdata(buf, length)
register char *buf;
register int length;
{
register int c;
register unsigned int crc;
register int d;
if (Rxframeind == ZBIN32)
return zrdat32(buf, length);
crc = Rxcount = 0;
for (;;) {
if ((c = zdlread()) & ~0377) {
crcfoo:
switch (c) {
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
crc = updcrc((d=c)&0377, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = updcrc(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = updcrc(c, crc);
if (crc & 0xFFFF) {
log2("Bad data CRC %x", crc);
return ERROR;
}
vfile("zrdata: cnt = %d ret = %x", Rxcount, d);
return d;
case GOTCAN:
log2("ZMODEM: Sender Canceled");
return ZCAN;
case TIMEOUT:
log2("ZMODEM data TIMEOUT");
return c;
default:
log2("ZMODEM bad data subpacket ret=%x", c);
return c;
}
}
if (--length < 0) {
log2("ZMODEM data subpacket too long");
return ERROR;
}
++Rxcount;
*buf++ = c;
crc = updcrc(c, crc);
continue;
}
}
zrdat32(buf, length)
register char *buf;
register int length;
{
register int c;
register unsigned long crc;
register int d;
crc = 0xFFFFFFFFL; Rxcount = 0;
for (;;) {
if ((c = zdlread()) & ~0377) {
crcfoo:
switch (c) {
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
crc = UPDC32((d=c)&0377, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = UPDC32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = UPDC32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = UPDC32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = UPDC32(c, crc);
if (crc != 0xDEBB20E3L) {
log2("Bad data CRC");
return ERROR;
}
vfile2("zrdat32: cnt = %ld ret = %x", Rxcount, d);
return d;
case GOTCAN:
log2("ZMODEM: Sender Canceled");
return ZCAN;
case TIMEOUT:
log2("ZMODEM data TIMEOUT");
return c;
default:
log2("ZMODEM bad data subpacket ret");
return c;
}
}
if (--length < 0) {
log2("ZMODEM data subpacket too long");
return ERROR;
}
++Rxcount;
*buf++ = c;
crc = UPDC32(c, crc);
continue;
}
}
/*
* Read a ZMODEM header to hdr, either binary or hex.
* eflag controls local display of non zmodem characters:
* 0: no display
* 1: display printing characters only
* 2: display all non ZMODEM characters
* On success, set Zmodem to 1 and return type of header.
* Otherwise return negative on error
*/
zgethdr(hdr, eflag)
register char *hdr;
register int eflag;
{
register int c, n, cancount;
n = Baudrate; /* Max characters before start of frame */
cancount = 5;
again:
Rxframeind = Rxtype = 0;
switch (c = noxread7()) {
case RCDO:
case TIMEOUT:
goto fifi;
case CAN:
if (--cancount <= 0) {
c = ZCAN; goto fifi;
}
/* **** FALL THRU TO **** */
default:
agn2:
if ( --n == 0) {
log2("ZMODEM Garbage count exceeded");
return(ERROR);
}
if (eflag && ((c &= 0177) & 0140))
bttyout(c);
else if (eflag > 1)
bttyout(c);
if (c != CAN)
cancount = 5;
goto again;
case ZPAD: /* This is what we want. */
break;
}
cancount = 5;
splat:
switch (c = noxread7()) {
case ZPAD:
goto splat;
case RCDO:
case TIMEOUT:
goto fifi;
default:
goto agn2;
case ZDLE: /* This is what we want. */
break;
}
switch (c = noxread7()) {
case RCDO:
case TIMEOUT:
goto fifi;
case ZBIN:
Rxframeind = ZBIN;
c = zrbhdr(hdr);
break;
case ZBIN32:
Rxframeind = ZBIN32;
c = zrbhdr32(hdr);
break;
case ZHEX:
Rxframeind = ZHEX;
c = zrhhdr(hdr);
break;
case CAN:
if (--cancount <= 0) {
c = ZCAN; goto fifi;
}
goto agn2;
default:
goto agn2;
}
Rxpos = hdr[ZP3] & 0377;
Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
R